// src/middleware/jwt.middleware
import { Inject, Middleware } from '@midwayjs/core';
import { Context, NextFunction } from '@midwayjs/koa';
import { JwtService } from '@midwayjs/jwt';
import { RespMethod } from '../util/common.method';
import { RespStatusCode } from '../types/common.type';
import { AccessLogService } from '../service/accesslog.service';
import { UserService } from '../service/user.service';
import { UserRole } from '../types/user.type';
var MobileDetect = require('mobile-detect')

@Middleware()
export class JwtMiddleware {

  @Inject()
  jwtService: JwtService;

  /** 配置忽略鉴权的路由地址 */
  noTokenPath: string[] = [
    '/v1/user/login',
    '/v1/user/register',
    '/v1/user/forgotpassword',
    '/email/register/code',
    '/email/forgotpassword/code',
    '/note/list',
    '/note/get',
    '/tool/list',
    '/common/reghref',
  ]

  public static getName(): string {
    return 'jwt';
  }

  resolve() {
    return async (ctx: Context, next: NextFunction) => {
      try {
        await this.setAccessLog(ctx);
      } catch (error) {
        console.log(error);
      }
      // 获取 接口 路径
      const apiPath = ctx.path;
      // 判断下有没有校验信息
      if (this.noTokenPath.some(val => val === apiPath)) {
        await next();
      } else if (ctx.headers['token']) {
        // 从 header 上获取校验信息
        const token = ctx.get('token');
        try {
          //jwt.verify方法验证token是否有效
          await this.jwtService.verify(token, { complete: true, });
        } catch (error) {
          return RespMethod({}, RespStatusCode.TokenExpire, 'Token 已过期，请重新登录');
        }
        await next();
      } else {
        return RespMethod({}, RespStatusCode.TokenEmpty, '未登录，请先登录');
      }
    };
  }


  /** 获取客户端的基础信息 */
  async setAccessLog(ctx: Context): Promise<void> {
    // 获取 接口 路径
    const apiPath = ctx.path;
    if (apiPath.includes('admin')) { return }
    // 注入 accessLogService 服务
    const accessLogService = await ctx.requestContext.getAsync(AccessLogService);
    // 注入 userService 服务
    const userService = await ctx.requestContext.getAsync(UserService);
    // 获取客户端 IP
    const forwarded = ctx.headers['x-forwarded-for'] || ctx.connection?.remoteAddress || ctx.socket?.remoteAddress || ctx.connection?.socket?.remoteAddress;
    // 获取 接口 路径
    const userAgent = ctx.headers['user-agent'];
    const md = new MobileDetect(userAgent);
    // 从 header 上获取校验信息
    const token = ctx.get('token');
    if (token) {
      const user = await userService.getUserByToken(token);
      if (user.data.role > UserRole.Root) {
        accessLogService.addlog(apiPath, forwarded, md.ua, user.data?.uid)
      }
    } else {
      accessLogService.addlog(apiPath, forwarded, md.ua)
    }
  }
}